import * as fs from 'fs';
import * as path from 'path';

import { nbaReq , nbaReqConfig , INbaReqOption , hostname , experience, position , form , series , schedule , mold , area } from './nba_api';

import { LeagueControl , TeamsControl , PlayerControl , SeasonControl , SeasonTypeControl , TeamRankDataControl , NBADataControl } from '../database/controller';
import { Leagues } from '../database/entity/leagues';
import { Teams } from '../database/entity/teams';
import { Players } from '../database/entity/players';
import { Season } from '../database/entity/season';
import { SeasonType } from '../database/entity/season_type';
import { TeamRankData } from '../database/entity/team_rank_data';
import { NBAData , NBADataType } from '../database/entity/nba_data';

export const crawlingNBAData = async () => {
    try {
        let teamOption: INbaReqOption = {
            hostname,
            path: nbaReqConfig.team,
        }
        let teamJSONString: string = await nbaReq(teamOption);
        let teamJSON: JSON = JSON.parse(teamJSONString);
        let league: Leagues = teamJSON["payload"]["league"];
        await LeagueControl.saveLeague(league);

        let teamLists: Array<JSON> = teamJSON["payload"]["listGroups"];
        let teams: Array<Teams> = [];
        teamLists.map(list => {
            let conferenceTeams: Array<JSON> = list["teams"];
            conferenceTeams.map(team => {
                let teamJSON: Teams = team["profile"];
                teamJSON.avatar = `https://${hostname}/media/img/teams/logos/${teamJSON.abbr}_logo.svg`;
                teamJSON.league = league;
                teams.push(teamJSON);
            })
        })
        await TeamsControl.saveTeam(teams);

        let playerOption: INbaReqOption = {
            hostname,
            path: nbaReqConfig.playerlist,
        }
        let playerJSONString: string = await nbaReq(playerOption);
        let playerParseJSON: JSON = JSON.parse(playerJSONString);
        let playerJSON: Array<JSON> = playerParseJSON["payload"]["players"];
        let players: Array<Players> = [];
        playerJSON.map(jsonObj => {
            let playerObj: any = jsonObj["playerProfile"];
            let { playerId , leagueId , ...playerRest } = playerObj;
            let teamObj: Teams = jsonObj["teamProfile"];
            playerRest.teams = teamObj;
            playerRest.league = league;
            playerRest.id = playerId;
            playerRest.avatar = `https://${hostname}/media/img/players/head/260x190/${playerId}.png`
            players.push(playerRest);
        })
        await PlayerControl.savePlayer(players);

        let seasonJSON = fs.readFileSync(path.resolve(__dirname,'../../public/season.json'),{
            encoding: 'utf8'
        });
        let season: Array<Season> = JSON.parse(seasonJSON);
        await SeasonControl.saveSeason(season);

        let seasonTypeJSON = fs.readFileSync(path.resolve(__dirname,'../../public/season_type.json'),{
            encoding: 'utf8'
        });
        let seasonType: Array<SeasonType> = JSON.parse(seasonTypeJSON);
        await SeasonTypeControl.saveSeasonType(seasonType);

        let teamRankOption: INbaReqOption = {
            hostname,
            path: nbaReqConfig.teamrank
        }
        let teamRankJSONString: string = await nbaReq(teamRankOption);
        let teamRankJSON: JSON = JSON.parse(teamRankJSONString);
        SeasonControl.querySeasonAll()
        .then((seasons: Season[]) => {
            SeasonTypeControl.querySeasonTypeAll()
            .then(async (seasonTypes: SeasonType[]) => {
                // 拉取队伍排名信息，china.nba网站只有当前赛季常规赛数据，所以写死
                let teamRankConfJSONArray: Array<JSON> = teamRankJSON["payload"]["standingGroups"];
                let teamRanks: Array<TeamRankData> = [];
                let teamRankSeason: Season = seasons.filter(season => season.name == '2018')[0];
                let teamRankSeasonType: SeasonType = seasonTypes.filter(seasonType => seasonType.name == '2')[0];
                teamRankConfJSONArray.map(teamRankConf => {
                    let teamsArrayJSON: Array<JSON> = teamRankConf["teams"];
                    teamsArrayJSON.map(teamsJSON => {
                        let teamsObj: Teams = teamsJSON['profile'];
                        let seasonObj: Season = teamRankSeason;
                        let seasonTypeObj: SeasonType = teamRankSeasonType;
                        let teamsRankObj: TeamRankData = teamsJSON['standings'];
                        teamsRankObj.teams = teamsObj;
                        teamsRankObj.season = seasonObj;
                        teamsRankObj.seasonType = seasonTypeObj;
                        teamRanks.push(teamsRankObj);
                    })
                })
                await TeamRankDataControl.saveTeamRankData(teamRanks);

                // 保存球员数据
                await savePlayerData()
                .then(() => {
                    // 保存队伍数据
                    seasons.map((season: Season) => {
                        seasonTypes.map(async (seasonType: SeasonType) => {
                            await saveTeamData(season,seasonType);
                        })
                    })
                })
            })
        })
    } catch (error) {
        console.log(`save nba whole data error; error message: ${error}`);
    }
}

export const saveTeamData = async (season: Season , seasonType: SeasonType) => {
    // 拉取队伍数据
    let nbaTeamDataOption: INbaReqOption = {
        hostname,
        path: nbaReqConfig.teamdata(season.name,seasonType.name)
    }
    let teamDataJSONString: string = await nbaReq(nbaTeamDataOption);
    let teamsArrs: Array<Teams> = await TeamsControl.queryTeamAll();
    let teamDataJSON: JSON = JSON.parse(teamDataJSONString);
    let teamReqDataJSON: Array<JSON> = teamDataJSON['payload']['teams'];
    let nbaTeamData: Array<NBAData> = [];
    teamReqDataJSON.map(async team => {
        let nbaTeam: Teams = team['profile'];
        let teamId: string = nbaTeam['id'];
        let teamYes: Array<Teams> = teamsArrs.filter(teama => teama.id == teamId);
        if(!teamYes || teamYes.length <= 0) return false;
        else {
            let stat: NBAData = {
                ...team['statAverage'],
                ...team['statTotal'],
            };
            stat.teams = nbaTeam;
            stat.season = season;
            stat.seasonType = seasonType;
            stat.dataType = NBADataType.TEAM;
            nbaTeamData.push(stat);
        }
    })
    await NBADataControl.saveNBAData(nbaTeamData);
}

export const formatPlayerData = (player: Players,seasonsAll: Array<Season>,seasonTypesAll: Array<SeasonType>,teamsAll: Array<Teams>): Promise<Array<NBAData>> => {
    return new Promise((resolve,reject) => {
        let nbaPlayerDataOption: INbaReqOption = {
            hostname,
            path: nbaReqConfig.playerdata(player.code)
        }
        try {
            nbaReq(nbaPlayerDataOption)
            .then((nbaPlayerDataJSONString: string) => {
                let singlePlayerAllData: Array<NBAData> = [];
                let nbaPlayerDataJSON: JSON = JSON.parse(nbaPlayerDataJSONString);
                let playerInfoJSON: JSON = nbaPlayerDataJSON['payload']['player'];
                let playerRightNowTeam: Teams = playerInfoJSON['teamProfile'];
                let playerRightNowTeamId: string = playerRightNowTeam.id;
                let playerRightNowTeamObject: Array<Teams> = teamsAll.filter((teams: Teams) => teams.id = playerRightNowTeamId);
                let nbaDataStatInfo: JSON = playerInfoJSON['stats'];
                // NBADataType.SEASON start
                let nbaDataStatCurrentSeasonJSON: JSON = nbaDataStatInfo['currentSeasonTypeStat'];
                let nbaDataSeasonCurrentSeasonJSON: JSON = nbaDataStatCurrentSeasonJSON['season'];
                let currentSeasonName: string = nbaDataSeasonCurrentSeasonJSON['year'];
                let currentSeasonTypeName: string = nbaDataSeasonCurrentSeasonJSON['type'];
                let nbaDataCurrentSeasonJSON: JSON = nbaDataStatCurrentSeasonJSON['currentSeasonTypePlayerTeamStats'][0];
                let currentSeasonResult: Array<Season> = seasonsAll.filter((season: Season) => season.name = currentSeasonName);
                let currentSeasonTypeResult: Array<SeasonType> = seasonTypesAll.filter((seasonType: SeasonType) => seasonType.name = currentSeasonTypeName);
                if(nbaDataCurrentSeasonJSON && Object.keys(nbaDataCurrentSeasonJSON).length > 0) {
                    let currentSeasonTeamId: string = nbaDataCurrentSeasonJSON['profile']['id'];
                    let curretnSeasonStatAverage: NBAData = nbaDataCurrentSeasonJSON['statAverage'];
                    let curretnSeasonStatTotal: NBAData = nbaDataCurrentSeasonJSON['statTotal'];
                    let seasonStats: NBAData = {
                        ...curretnSeasonStatAverage,
                        ...curretnSeasonStatTotal,
                    }
                    let currentTeamResult: Array<Teams> = teamsAll.filter((teams: Teams) => teams.id = currentSeasonTeamId);
                    seasonStats.dataType = NBADataType.SEASON;
                    playerRightNowTeamObject && playerRightNowTeamObject.length > 0 && (seasonStats.teams = playerRightNowTeamObject[0]);
                    currentTeamResult && currentTeamResult.length > 0 && (seasonStats.rightAwayTeam = currentTeamResult[0]);
                    seasonStats.season = currentSeasonResult[0];
                    seasonStats.seasonType = currentSeasonTypeResult[0];
                    seasonStats.players = player;
                    singlePlayerAllData.push(seasonStats);
                    // NBADataControl.saveNBADataSingle(seasonStats);
                }
                // NBADataType.GAMES start
                let seasonGamesNBADatas: Array<NBAData> = formatGames(nbaDataStatInfo,player,playerRightNowTeamObject,currentSeasonResult[0],currentSeasonTypeResult[0],teamsAll);
                singlePlayerAllData.push(...seasonGamesNBADatas);
                // NBADataType.GAMES end

                // NBADataType.REGULAR start
                let regularNBADatas: Array<NBAData> = formatData(nbaDataStatInfo,'regularSeasonStat',playerRightNowTeamObject,seasonsAll,seasonTypesAll,teamsAll,NBADataType.REGULAR,player,'2');
                singlePlayerAllData.push(...regularNBADatas);
                // NBADataType.REGULAR end
                // NBADataType.PLAYOFF start
                let playoffNBADatas: Array<NBAData> = formatData(nbaDataStatInfo,'playoffStat',playerRightNowTeamObject,seasonsAll,seasonTypesAll,teamsAll,NBADataType.PLAYOFF,player,'4');
                singlePlayerAllData.push(...playoffNBADatas);
                // NBADataType.PLAYOFF end
                // NBADataType.ALLSTAR start
                let allstarNBADatas: Array<NBAData> = formatData(nbaDataStatInfo,'allStarStat',playerRightNowTeamObject,seasonsAll,seasonTypesAll,teamsAll,NBADataType.ALLSTAR,player);
                singlePlayerAllData.push(...allstarNBADatas);
                // NBADataType.ALLSTAR end
                // NBADataType.REGULACAREER start
                let regularCareerJSON: JSON = nbaDataStatInfo['regularSeasonCareerStat'];
                if(regularCareerJSON && Object.keys(regularCareerJSON).length > 0) {
                    let regularCareerDatas: NBAData = {
                        ...regularCareerJSON['statAverage'],
                        ...regularCareerJSON['statTotal'],
                    }
                    regularCareerDatas.players = player;
                    playerRightNowTeamObject && playerRightNowTeamObject.length > 0 && (regularCareerDatas.teams = playerRightNowTeamObject[0]);
                    regularCareerDatas.dataType = NBADataType.REGULACAREER;
                    singlePlayerAllData.push(regularCareerDatas);
                    // NBADataControl.saveNBADataSingle(regularCareerDatas);
                }
                // NBADataType.REGULACAREER end
                // NBADataType.PLAYOFFCAREER start
                let playoffCareerJSON: JSON = nbaDataStatInfo['playoffCareerStat'];
                if(playoffCareerJSON && Object.keys(playoffCareerJSON).length > 0) {
                    let playoffCareerDatas: NBAData = {
                        ...playoffCareerJSON['statAverage'],
                        ...playoffCareerJSON['statTotal'],
                    }
                    playoffCareerDatas.players = player;
                    playerRightNowTeamObject && playerRightNowTeamObject.length > 0 && (playoffCareerDatas.teams = playerRightNowTeamObject[0]);
                    playoffCareerDatas.dataType = NBADataType.PLAYOFFCAREER;
                    singlePlayerAllData.push(playoffCareerDatas);
                    // NBADataControl.saveNBADataSingle(playoffCareerDatas);
                }
                // NBADataType.PLAYOFFCAREER end
                // NBADataType.SPLITS start
                let splitDataJSON: Array<JSON> = nbaDataStatInfo['playerSplit']['splits'];
                if(splitDataJSON && splitDataJSON.length > 0) {
                    let splitDataArrs: Array<NBAData> = [];
                    splitDataJSON.map(async splitData => {
                        let splitDatas: NBAData = {
                            ...splitData['statAverage'],
                            ...splitData['statTotal'],
                        }
                        splitDatas.players = player;
                        splitDatas.splitName = splitData['name'];
                        playerRightNowTeamObject && playerRightNowTeamObject.length > 0 && (splitDatas.teams = playerRightNowTeamObject[0]);
                        splitDatas.splitDisplayName = splitData['displayName'];
                        splitDatas.dataType = NBADataType.SPLITS;
                        splitDataArrs.push(splitDatas);
                    })
                    singlePlayerAllData.push(...splitDataArrs);
                    // await NBADataControl.saveNBAData(splitDataArrs);
                }
                // NBADataType.SPLITS end
                // await NBADataControl.saveNBAData(singlePlayerAllData)
                // .then(result => {
                //     fs.writeFile(path.resolve(__dirname,'../../log.txt'),`save request options= ${JSON.stringify(nbaPlayerDataOption)};singlePlayerAllData length = ${singlePlayerAllData.length};\n`,{
                //         flag: 'a+',
                //     },err => {
                //         if (err) console.log(err);
                //     })
                // })
                fs.writeFileSync(path.resolve(__dirname,'../../log.txt'),`save request options= ${JSON.stringify(nbaPlayerDataOption)};singlePlayerAllData length = ${singlePlayerAllData.length};\n`,{
                    flag: 'a+',
                })
                resolve(singlePlayerAllData);

                // fs.writeFile(path.resolve(__dirname,'../../log.txt'),`save request options= ${JSON.stringify(nbaPlayerDataOption)};singlePlayerAllData length = ${singlePlayerAllData.length};singlePlayerAllData detail = ${JSON.stringify(singlePlayerAllData)};`,{
                //     flag: 'a+',
                // },err => {
                //     if (err) console.log(err);
                // })
            })
            .catch(error => {
                throw new Error(error);
                reject();
                fs.writeFileSync(path.resolve(__dirname,'../../reqerrlog.txt'),`save request options= ${JSON.stringify(nbaPlayerDataOption)};error = ${JSON.stringify(error)}\n`,{
                    flag: 'a+',
                })
            })
        } catch (error) {
            throw new Error(error);
            reject();
            fs.writeFileSync(path.resolve(__dirname,'../../errlog.txt'),`save request options= ${JSON.stringify(nbaPlayerDataOption)};error = ${JSON.stringify(error)}\n`,{
                flag: 'a+',
            })
        }
    })
}

export const savePlayerData = async () => {
    let allNBAData: Array<NBAData> = [];
    await SeasonControl.querySeasonAll()
    .then(async (seasonsAll: Array<Season>) => {
        SeasonTypeControl.querySeasonTypeAll()
        .then(async (seasonTypesAll: Array<SeasonType>) => {
            TeamsControl.queryTeamAll()
            .then(async (teamsAll: Array<Teams>) => {
                PlayerControl.queryPlayersAll()
                .then((playersAll: Array<Players>) => {
                    playersAll.map(async (player: Players,index: number) => {
                        try {
                            let datasArray: Array<NBAData> = await formatPlayerData(player,seasonsAll,seasonTypesAll,teamsAll);
                            allNBAData.push(...datasArray);
                            await ormSave(datasArray);
                        } catch (error) {
                            console.log(error);
                        }
                    })
                })
            })
        })
    })
}

export const ormSave = async (datas: Array<NBAData>) => {
    await NBADataControl.saveNBAData(datas)
    .then(() => {
        fs.writeFileSync(path.resolve(__dirname,'../../successlog.txt'),`save success;datas length = ${datas.length};\n`,{
            flag: 'a+',
        })
    })
    .catch(error => fs.writeFileSync(path.resolve(__dirname,'../../errlog.txt'),`orm save error ; error = ${JSON.stringify(error)}\n`,{
        flag: 'a+',
    }))
}

export const formatGames = (nbaDataStatInfo: JSON,player: Players,teams: Array<Teams>,currentSeason: Season,currentSeasonType: SeasonType,teamsAll: Array<Teams>): Array<NBAData> => {
    let seasonGamesNBADatas: Array<NBAData> = [];
    let gamesDataArrayJSON: Array<JSON> = nbaDataStatInfo['seasonGames'];
    if(gamesDataArrayJSON && gamesDataArrayJSON.length > 0) {
        gamesDataArrayJSON.map((gamesDataJSON: JSON) => {
            let gamesTeamProfile: JSON = gamesDataJSON['profile'];
            let gamesTeamId: string = gamesTeamProfile['teamProfile']['id'];
            let gameOppTeamId: string = gamesTeamProfile['oppTeamProfile']['id'];
            let gamesTeamResult: Array<Teams> = teamsAll.filter((teams: Teams) => teams.id = gamesTeamId);
            let gamesOppTeamResult: Array<Teams> = teamsAll.filter((teams: Teams) => teams.id = gameOppTeamId);
            let gamesTeam: Teams = gamesTeamResult[0];
            let gamesOppTeam: Teams = gamesOppTeamResult[0];
            let gamesNbaData: NBAData = gamesDataJSON['statTotal'];
            gamesNbaData.gameId = gamesTeamProfile['gameId'];
            gamesNbaData.isHome = gamesTeamProfile['isHome'];
            gamesNbaData.oppTeamScore = gamesTeamProfile['oppTeamScore'];
            gamesNbaData.teamScore = gamesTeamProfile['teamScore'];
            gamesNbaData.utcMillis = gamesTeamProfile['utcMillis'];
            gamesNbaData.winOrLoss = gamesTeamProfile['winOrLoss'];
            teams && teams.length > 0 && (gamesNbaData.teams = teams[0]);
            gamesTeam && (gamesNbaData.rightAwayTeam = gamesTeam);
            gamesOppTeam && (gamesNbaData.oppTeams = gamesOppTeam);
            gamesNbaData.players = player;
            gamesNbaData.season = currentSeason;
            gamesNbaData.seasonType = currentSeasonType;
            gamesNbaData.dataType = NBADataType.GAMES;
            seasonGamesNBADatas.push(gamesNbaData);
            // await NBADataControl.saveNBADataSingle(gamesNbaData);
        })
    }
    return seasonGamesNBADatas;
}

export const formatData = (nbaDataStatInfo: JSON, jsonKey: string ,playerRightNowTeamObject: Array<Teams>,seasonsAll: Array<Season>,seasonTypesAll: Array<SeasonType>,teamsAll: Array<Teams> , dataType: NBADataType , player: Players , SeaonTypeName?: string): Array<NBAData> => {
    let statNBADatas: Array<NBAData> = [];
    let nbaDataJSON: Array<JSON> = nbaDataStatInfo[jsonKey]['playerTeams'];
    if(nbaDataJSON && nbaDataJSON.length > 0) {
        nbaDataJSON.map(nbaData => {
            let SesonTeamId: string = nbaData['profile'] ? nbaData['profile']['id'] : '';
            let SeaonName: string = nbaData['season'];
            if(!!SesonTeamId) {
                let currentSeasonResult: Array<Season> = seasonsAll.filter((season: Season) => season.name = SeaonName);
                let currentSeasonTypeResult: Array<SeasonType> = seasonTypesAll.filter((seasonType: SeasonType) => seasonType.name = SeaonTypeName);
                let currentTeamResult: Array<Teams> = teamsAll.filter((teams: Teams) => teams.id = SesonTeamId);
                let Stats: NBAData = {
                    ...nbaData['statAverage'],
                    ...nbaData['statTotal'],
                }
                Stats.dataType = dataType;
                playerRightNowTeamObject && playerRightNowTeamObject.length > 0 && (Stats.teams = playerRightNowTeamObject[0]);
                dataType !== NBADataType.ALLSTAR && (Stats.rightAwayTeam = currentTeamResult[0]);// 目前没有存入全明星球队数据，所以全明星数据必定无法找到球队，暂时先不存吧
                Stats.season = currentSeasonResult[0];
                dataType !== NBADataType.ALLSTAR && (Stats.seasonType = currentSeasonTypeResult[0]);
                Stats.players = player;
                statNBADatas.push(Stats);
                // await NBADataControl.saveNBADataSingle(Stats)
            }else {
                let currentSeasonResult: Array<Season> = seasonsAll.filter((season: Season) => season.name = SeaonName);
                let currentSeasonTypeResult: Array<SeasonType> = seasonTypesAll.filter((seasonType: SeasonType) => seasonType.name = SeaonTypeName);
                let Stats: NBAData = {
                    ...nbaData['statAverage'],
                    ...nbaData['statTotal'],
                }
                Stats.dataType = dataType;
                // playerRightNowTeamObject && playerRightNowTeamObject.length > 0 && (Stats.teams = playerRightNowTeamObject[0]);
                // dataType !== NBADataType.ALLSTAR && (Stats.teams = SeaonTeam);// 目前没有存入全明星球队数据，所以全明星数据必定无法找到球队，暂时先不存吧
                Stats.season = currentSeasonResult[0];
                dataType !== NBADataType.ALLSTAR && (Stats.seasonType = currentSeasonTypeResult[0]);
                Stats.players = player;
                statNBADatas.push(Stats);
                // await NBADataControl.saveNBADataSingle(Stats);
            }
        })
    }
    return statNBADatas;
}